# -*- coding: utf-8 -*-

import logging
from google.appengine.ext import db
import yaml

class NotUniqueError(Exception):
	def __init__(self, key):
		self.key = key
	def __str__(self):
		return key+ " not unique"

class MyModel(db.Model):
	_unique = set()
	_searchable = set()

	def dump(self, otherData={}):
		data = self.properties()
		for key in data.keys():
			try:
				data[key] = self.__getattribute__(key)
			except KeyError:
				pass
		data['key'] = str(self.key())
		data['type'] = self.__class__.__name__

		data.update(otherData)
		logging.info(data)
		output = yaml.dump(data)
		return output

	@classmethod
	def _insert(cls, yml, user=None):
		if type(yml) == str:
			data = yaml.load(yml)
		else:
			data = yml
		
		logging.info("Recieved data: " +str(data))
		for i in cls._unique:
			if i in data.keys() and not cls.isUnique(i, data[i]):
				raise NotUniqueError(i)

		obj = cls()
		for key in data:
			if key in obj.properties().keys():
				logging.info("Trying to set "+key+" to "+str(data[key]))
				obj.__setattr__(key, data[key])

		if user:
			obj.user = user

		obj.put()
		return obj

	@classmethod
	def insert(cls, yml, user):
		return cls._insert(yml, user)

	def update(self, yml, user):
		if type(yml) == str:
			data = yaml.load(yml)
		else:
			data = yml
		logging.info(data.keys())
		for i in self._unique:
			if i in data.keys() and not self.isUnique(i, data[i], self.key()):
				raise NotUniqueError(i)

		for key in data:
			if key in self.properties().keys():
				self.__setattr__(key, data[key])
				
		self.user = user
		
		self.put()

	@classmethod
	def _search(cls, yml):
		if type(yml) == str:
			data = yaml.load(yml)
		else:
			data = yml

		keys = []
		query = "SELECT __key__ FROM " + cls.__name__ + " WHERE %s = :1"
		for prop in cls._searchable:
			if prop in data.keys():
				if type(data[prop])==str:
					data[prop] = data[prop]
				if type(data[prop])==bool:
					if data[prop]:
						data[prop] = "TRUE"
					else:
						data[prop] = "FALSE"
				logging.info(query % (prop))
				logging.info(str(data))
				q = db.GqlQuery(query % (prop), data[prop])
				keys.extend(q.fetch(1000))
		keys = [str(i) for i in keys]
		logging.info(keys)
		return keys

	@classmethod
	def search(cls, yml):
		return cls._search(yml)

	@classmethod
	def isUnique(cls, property, value, key=None):
		if not value:
			return True
		query = cls.gql("WHERE "+property+" = :1", value)
		if not key:
			if query.count() > 0:
				return False
			else:
				return True
		else:
			a = query.get()
			if not a:
				return True
			elif a.key() == key:
				return True
			else:
				return False

